/*
 * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

/*!
 * @file mt9v139.c
 *
 * @brief mt9v139 camera driver functions
 *
 * @ingroup Camera
 */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <mach/gpio.h>

#include <linux/i2c.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/fsl_devices.h>
#include <media/v4l2-int-device.h>
#include "mxc_v4l2_capture.h"
//#include "mt9v139.h"

#define MT9V139_FRAME_RATE        30
#define MT9V139_MCLK              27000000 /* Desired clock rate */
#define MT9V139_CLK_MIN           12000000 /* This clock rate yields 15 fps */
#define MT9V139_CLK_MAX           27000000
#define MT9V139_MAX_WIDTH         640      /* Max width for this camera */
#define MT9V139_MAX_HEIGHT        480      /* Max height for this camera */



#define SYSMGR_SET_STATE  0x8100
#define SYSMGR_GET_STATE  0x8101

// Sequencer commands
#define SEQ_REFRESH  		0x8606
#define SEQ_REFRESH_STATUS	0x8607	

enum {
SYS_STATE_OTPM_DEFAULTS 		= 0x10,
SYS_STATE_OTPM_CONFIG			= 0x11,
SYS_STATE_OC_LOAD_DEFAULTS		= 0x12,
SYS_STATE_OC_LOAD_PATCHES		= 0x13,
SYS_STATE_OC_LOAD_CALIB 		= 0x14,
SYS_STATE_OC_CONFIG_TASKS		= 0x15,
SYS_STATE_OC_COMPLETE			= 0x16,
SYS_STATE_AUTO_CONFIG			= 0x17,
SYS_STATE_HOST_CONFIG			= 0x18,
SYS_STATE_FLASH_CONFIG			= 0x19,
SYS_STATE_FC_LOAD_DEFAULTS		= 0x1A,
SYS_STATE_FC_LOAD_PATCHES		= 0x1B,
SYS_STATE_FC_LOAD_CALIB 		= 0x1C,
SYS_STATE_FC_CONFIG_TASKS		= 0x1D,
SYS_STATE_FC_COMPLETE			= 0x1E,
SYS_STATE_CONFIG_COMPLETE		= 0x1F,
SYS_STATE_ENTER_CONFIG_CHANGE	= 0x28,
SYS_STATE_STREAMING 			= 0x31,
SYS_STATE_START_STREAMING		= 0x34,
SYS_STATE_ENTER_SUSPEND 		= 0x40,
SYS_STATE_SUSPENDED 			= 0x41,
SYS_STATE_ENTER_STANDBY 		= 0x50,
SYS_STATE_STANDBY				= 0x52,
SYS_STATE_LEAVE_STANDBY 		= 0x54,
SYS_STATE_DO_RESYNC 			= 0x60,
SYS_STATE_LEAVE_RESYNC			= 0x61,
SYS_STATE_UNKNOWN				= 0xFF,
};



/*
 * macro of read/write
 */
#define ECHECKER(ret, x)		\
	do {				\
		(ret) = (x);		\
		if ((ret) < 0)		\
			return (ret);	\
	} while (0)

#define i2c_reg_write32(ret, client, a, b) \
	ECHECKER(ret, __i2c_reg_write32(client, a, b))


#define i2c_reg_write(ret, client, a, b) \
	ECHECKER(ret, __i2c_reg_write(client, a, b))
	
#define i2c_reg_write8(ret, client, a, b) \
		ECHECKER(ret, __i2c_reg_write8(client, a, b))


#define i2c_mcu_write(ret, client, a, b) \
	ECHECKER(ret, __i2c_mcu_write(client, a, b))

#define i2c_reg_mask_set(ret, client, a, b, c) \
	ECHECKER(ret, __i2c_reg_mask_set(client, a, b, c))
#define i2c_mcu_mask_set(ret, client, a, b, c) \
	ECHECKER(ret, __i2c_mcu_mask_set(client, a, b, c))

#define i2c_reg_read32(ret, client, a) \
	ECHECKER(ret, __i2c_reg_read32(client, a))

#define i2c_reg_read(ret, client, a) \
	ECHECKER(ret, __i2c_reg_read(client, a))

#define _VAR(id, offset, base)	(base | (id & 0x1f) << 10 | (offset & 0x3ff))
#define VAR(id, offset)  _VAR(id, offset, 0x8000)



#ifdef MT9V139_DEBUG
static u16 testpattern;
#endif

#define VOLTAGE_DIGITAL         2800000

enum sensor_mode {
	sensor_mode_MIN = 0,
	sensor_mode_VGA_640_480 = 0,
	sensor_mode_QVGA_320_240 = 1,
	sensor_mode_NTSC_720_480 = 2,
	sensor_mode_PAL_720_576 = 3,
	sensor_mode_720P_1280_720 = 4,
	sensor_mode_1080P_1920_1080 = 5,
	sensor_mode_QSXGA_2592_1944 = 6,
	sensor_mode_QCIF_176_144 = 7,
	sensor_mode_MAX = 7
};

enum ov5642_frame_rate {
	frame_rate_15_fps,
	frame_rate_30_fps
};


typedef struct  {
	u16 RegAddr;
	u16 Val;
	u16 Mask;
	u32 Delay_ms;
}reg_value_t;

typedef struct  {
	int mode;
	u32 width;
	u32 height;
	reg_value_t *init_data_ptr;
	u32 init_data_size;
}mode_info_t;

//reg.CAM_SENSOR_CFG_X_ADDR_START = 0x28
//reg.CAM_SENSOR_CFG_Y_ADDR_START = 0x24
//reg.CAM_SENSOR_CFG_X_ADDR_END = 0x2AF
//reg.CAM_SENSOR_CFG_Y_ADDR_END = 0x20B
//reg.CAM_SENSOR_CFG_LINE_LENGTH_PCK = 0x356
//reg.CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN = 0x99
//reg.CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX = 0x2ED
//reg.CAM_SENSOR_CFG_FINE_CORRECTION = 0x26
//reg.CAM_SENSOR_CFG_CPIPE_LAST_ROW = 0x1E3
//reg.CAM_SENSOR_CFG_FRAME_LENGTH_LINES = 0x3E8
//reg.CAM_SENSOR_CFG_LINE_LENGTH_PCK = 0x384
//reg.CAM_AET_AEMODE.CAM_AET_DISCRETE_FRAMERATE = 0
//reg.CAM_AET_MAX_FRAME_RATE = 0x1E00                 # 30.0
//reg.CAM_AET_MIN_FRAME_RATE = 0x500                  # 5.0
//reg.CAM_OUTPUT_WIDTH = 0x280
//reg.CAM_OUTPUT_HEIGHT = 0x1E0
//reg.CAM_OUTPUT_FORMAT.CAM_OUTPUT_FORMAT_FORMAT = 0x0
//reg.CAM_OUTPUT_FORMAT_YUV.CAM_OUTPUT_FORMAT_YUV_SELECT_601 = 0x8

//VGA - variable frame-rate (30 to 5 fps)
#if 0
REG = 0xC800, 0x0024		//cam_sensor_cfg_y_addr_start = 36
REG = 0xC802, 0x0028		//cam_sensor_cfg_x_addr_start = 40
REG = 0xC804, 0x020B		//cam_sensor_cfg_y_addr_end = 523
REG = 0xC806, 0x02AF		//cam_sensor_cfg_x_addr_end = 687
REG = 0xC808, 0x019BFCC0		//cam_sensor_cfg_pixclk = 27000000
REG = 0xC80C, 0x0099		//cam_sensor_cfg_fine_integ_time_min = 153
REG = 0xC80E, 0x02F3		//cam_sensor_cfg_fine_integ_time_max = 755
REG = 0xC810, 0x020B		//cam_sensor_cfg_frame_length_lines = 523
REG = 0xC812, 0x035C		//cam_sensor_cfg_line_length_pck = 860
REG = 0xC814, 0x0026		//cam_sensor_cfg_fine_correction = 38
REG = 0xC816, 0x01E3		//cam_sensor_cfg_cpipe_last_row = 483
REG = 0xC838, 0x0000		//cam_sensor_control_read_mode = 0
REG = 0xC858, 0x0011		//cam_frame_scan_control = 17
REG = 0xC968, 0x0280		//cam_output_width = 640
REG = 0xC96A, 0x01E0		//cam_output_height = 480
REG = 0xC864, 0x01		//cam_zoom_factor = 1
REG = 0xC86C, 0x00		//cam_aet_aemode = 0
REG = 0xC872, 0x0409		//cam_aet_ae_min_virt_int_time_pclk = 1033
REG = 0xC882, 0x3C00		//cam_aet_max_frame_rate = 15360
REG = 0xC884, 0x3C00		//cam_aet_min_frame_rate = 15360
REG = 0xC924, 0x15		//cam_stat_calcmode = 21
#endif


reg_value_t reg_val_vga_640X480_30[] = {
		{0xC802,0x0028,0xffff},
		{0xC800,0x0024,0xffff},
		{0xC806,0x02AF,0xffff},
		{0xC804,0x020B,0xffff},
		{0xC812,0x0356,0xffff},
		{0xC80C,0x0099,0xffff},
		{0xC80E,0x02ED,0xffff},
		{0x3010,0x0026,0xffff},
		{0xC816,0x01E3,0xffff},
		{0xC810,0x03E8,0xffff},
		{0xC812,0x0384,0xffff},
		{0xC86C,0x0000,BIT(1)},
		{0xC882,0x1E00,0xffff},
		{0xC884,0x0500,0xffff},
		{0xC968,0x0280,0xffff},
		{0xC96A,0x01E0,0xffff},
		{0xC96C,0X000,BIT(9)| BIT(8)},
		{0xC96E,BIT(3),BIT(3)  },
	};


mode_info_t g_mode_info={
	.mode = 0,
	.width = 640,
	.height = 480,
	.init_data_ptr = &reg_val_vga_640X480_30[0],
	.init_data_size=sizeof(reg_val_vga_640X480_30)/sizeof(reg_val_vga_640X480_30[0]),
};




/*!
 * Holds the current frame rate.
 */

typedef struct {
	//const struct mt9v139_platform_data *platform_data;
	//struct v4l2_subdev	 subdev;
	struct mxc_camera_platform_data *platform_data;
	struct v4l2_int_device *v4l2_int_device;
	struct i2c_client *i2c_client;
	struct v4l2_pix_format pix;
	struct v4l2_captureparm streamcap;
	int power_on;
	unsigned int mclk;
	unsigned int csi;

	/* control settings */
	int brightness;
	int hue;
	int contrast;
	int saturation;
	int red;
	int green;
	int blue;
	int ae_mode;
	struct regulator *core_regulator;
}sensor_data_t;

sensor_data_t sensor_data;







static int mt9v139_probe(struct i2c_client *client,
			 const struct i2c_device_id *id);
static int mt9v139_remove(struct i2c_client *client);
static int mt9v139_config(struct i2c_client *client);



/************************************************************************
			general function
************************************************************************/

static int __i2c_reg_read32(const struct i2c_client *client, u16 command)
{
	struct i2c_msg msg[2];
	u8 buf[4];
	int ret;

	command = swab16(command);

	msg[0].addr  = client->addr;
	msg[0].flags = 0;
	msg[0].len   = 2;
	msg[0].buf   = (u8 *)&command;

	msg[1].addr  = client->addr;
	msg[1].flags = I2C_M_RD;
	msg[1].len   = 4;
	msg[1].buf   = buf;

	/*
	 * if return value of this function is < 0,
	 * it mean error.
	 * else, under 16bit is valid data.
	 */
	ret = i2c_transfer(client->adapter, msg, 2);
	if (ret < 0)
		return ret;

	memcpy(&ret, buf, 4);
	return swab32(ret);
}


static int __i2c_reg_read(const struct i2c_client *client, u16 command)
{
	struct i2c_msg msg[2];
	u8 buf[2];
	int ret;

	command = swab16(command);

	msg[0].addr  = client->addr;
	msg[0].flags = 0;
	msg[0].len   = 2;
	msg[0].buf   = (u8 *)&command;

	msg[1].addr  = client->addr;
	msg[1].flags = I2C_M_RD;
	msg[1].len   = 2;
	msg[1].buf   = buf;

	/*
	 * if return value of this function is < 0,
	 * it mean error.
	 * else, under 16bit is valid data.
	 */
	ret = i2c_transfer(client->adapter, msg, 2);
	if (ret < 0)
		return ret;

	memcpy(&ret, buf, 2);
	return swab16(ret);
}

static int __i2c_reg_write(const struct i2c_client *client,
			       u16 command, u16 data)
{
	struct i2c_msg msg;
	u8 buf[4];
	int ret;

	command = swab16(command);
	data = swab16(data);

	memcpy(buf + 0, &command, 2);
	memcpy(buf + 2, &data,    2);

	msg.addr  = client->addr;
	msg.flags = 0;
	msg.len   = 4;
	msg.buf   = buf;

	/*
	 * i2c_transfer return message length,
	 * but this function should return 0 if correct case
	 */
	ret = i2c_transfer(client->adapter, &msg, 1);
	if (ret >= 0)
		ret = 0;

	return ret;
}


static int __i2c_reg_write32(const struct i2c_client *client,
			       u16 command, u32 data)
{
	struct i2c_msg msg;
	u8 buf[8];
	int ret;

	command = swab16(command);
	data = swab32(data);

	memcpy(buf + 0, &command, 2);
	memcpy(buf + 2, &data,    4);

	msg.addr  = client->addr;
	msg.flags = 0;
	msg.len   = 6;
	msg.buf   = buf;

	/*
	 * i2c_transfer return message length,
	 * but this function should return 0 if correct case
	 */
	ret = i2c_transfer(client->adapter, &msg, 1);
	if (ret >= 0)
		ret = 0;

	return ret;
}



static int __i2c_reg_write8(const struct i2c_client *client,
			       u16 command, u8 data)
{
	struct i2c_msg msg;
	u8 buf[4];
	int ret;

	command = swab16(command);

	memcpy(buf + 0, &command, 2);
	memcpy(buf + 2, &data,    1);

	msg.addr  = client->addr;
	msg.flags = 0;
	msg.len   = 3;
	msg.buf   = buf;

	/*
	 * i2c_transfer return message length,
	 * but this function should return 0 if correct case
	 */
	ret = i2c_transfer(client->adapter, &msg, 1);
	if (ret >= 0)
		ret = 0;

	return ret;
}


static int __i2c_reg_mask_set(const struct i2c_client *client,
				  u16  command,
				  u16  mask,
				  u16  set)
{
 int val = __i2c_reg_read(client, command);
	if (val < 0)
		return val;

	val &= ~mask;
	val |= set & mask;

	return __i2c_reg_write(client, command, val);
}

/* mcu access */
static int __i2c_mcu_read(const struct i2c_client *client, u16 command)
{
	int ret;

	ret = __i2c_reg_write(client, 0x098E, command);
	if (ret < 0)
		return ret;

	return __i2c_reg_read(client, 0x0990);
}

static int __i2c_mcu_write(const struct i2c_client *client,
			       u16 command, u16 data)
{
	int ret;

	ret = __i2c_reg_write(client, 0x098E, command);
	if (ret < 0)
		return ret;

	return __i2c_reg_write(client, 0x0990, data);
}

static int __i2c_mcu_mask_set(const struct i2c_client *client,
				  u16  command,
				  u16  mask,
				  u16  set)
{
	int val = __i2c_mcu_read(client, command);
	if (val < 0)
		return val;

	val &= ~mask;
	val |= set & mask;

	return __i2c_mcu_write(client, command, val);
}




static const struct i2c_device_id mt9v139_id[] = {
	{"mt9v139", 0},
	{},
};

MODULE_DEVICE_TABLE(i2c, mt9v139_id);

static struct i2c_driver mt9v139_i2c_driver = {
	.driver = {
		   .owner = THIS_MODULE,
		   .name = "mt9v139",
		   },
	.probe = mt9v139_probe,
	.remove = mt9v139_remove,
	.id_table = mt9v139_id,
/* To add power management add .suspend and .resume functions */
};





int host_command(struct i2c_client *client, u16 command){
	int retval=0;
	u16 regval=0;
	int i=0;
	i2c_reg_write(retval,client,0x0040,command);
	for(i=0;i<10;i++){
		i2c_reg_read(regval, client, 0x40);				
		if(regval & BIT(15)){
			pr_info("%s.%d hostcmd success retval(%x)\n",__func__,__LINE__,regval);
			return regval & 0xffff;
		}
		msleep(1);
	}
	pr_info("%s.%d hostcmd fail retval(%x)\n",__func__,__LINE__,regval);
	return retval;	
}


int sysmgrSetState(struct i2c_client *client,u16 state){
	int retval=0;
	i2c_reg_write(retval,client,VAR(0x1F,0x0000),(state<<8));	
	ECHECKER(retval, host_command(client, SYSMGR_SET_STATE));	
	pr_info("%s.%d retval(%x)\n",__func__,__LINE__,retval);
	return retval;
}	

int sysmgrGetState(struct i2c_client *client){
	int retval=0;
	int regval=0;
	ECHECKER(retval, host_command(client, SYSMGR_GET_STATE));	
	msleep(1);
	i2c_reg_read(regval, client, VAR(0x1F,0x0000));
	pr_info("%s.%d retval(%x)\n",__func__,__LINE__,regval);
	return (regval>>8);
}

int systemWaitReadyFollowingReset(struct i2c_client *client){
	u16 regval=0;
	int retval =0;
	int i=0;
	pr_info("%s.%d retval(%x)\n",__func__,__LINE__,retval);	
	for(i=0;i<100;i++){
		i2c_reg_read(regval, client, 0040);	
		if(regval & BIT(15)==0){
			pr_info("%s.%d system is ready retval(%x)\n",__func__,__LINE__,retval);

			break;
		}
		msleep(1);
	}	
	retval = sysmgrGetState(client);
	if(i==100){
		
		pr_info("%s.%d system is ready retval(%x)\n",__func__,__LINE__,retval);
		return -1;
	}
	

	
	return retval;
}


#define MX53_CSI0_RSTB		    (4*32 + 22)	/* GPIO_5_22 */

static int mt9v139_reset(const struct i2c_client *client)
{
	int retval=0;

	i2c_reg_mask_set(retval, client, 0x001a, 0x0001, 0x0001);
	msleep(1);
	i2c_reg_mask_set(retval, client, 0x001a, 0x0001, 0x0000);
	retval = systemWaitReadyFollowingReset(client);
	return retval;
}




/*API function: waits for the system to be ready following reset (or powerup)
       - first wait for the doorbell bit to clear - this indicates that the device can
         accept host commands.
       - then wait until the system has completed its configuration phase; the system is 
         ready when the SYSMGR_GET_STATE command does not return EBUSY.
       - note the time for the system to be ready is dependent upon the active system 
         configuration mode.
       - numRetries is the number of retries before timing-out
       - returns result status code
    */



int camera_hw_reset(const struct i2c_client *client){
#if 1	
	int retval;
	gpio_direction_output(MX53_CSI0_RSTB,0);
	msleep(1);
	gpio_direction_output(MX53_CSI0_RSTB,1);
	msleep(1);
	retval = systemWaitReadyFollowingReset(client);
#endif	
	return 0;
}

int Load_PLL(struct i2c_client *client){
	int retval=0;
	i2c_reg_write(retval, client,0xC962, 0x0001);		//cam_sysctl_pll_control = 1
	i2c_reg_write(retval, client,0xC964, 0x0118);		//cam_sysctl_pll_divider_m_n = 280
	i2c_reg_write(retval, client,0xC966, 0x0200);		//cam_sysctl_pll_divider_p = 512
	i2c_reg_write(retval, client,0xC972, 0x0005);		//cam_port_parallel_control = 5
	return retval;
}	


int Load_640X480(struct i2c_client *client){
	int retval=0;
	i2c_reg_write(retval, client,0xC800, 0x0024);		//cam_sensor_cfg_y_addr_start = 36
	i2c_reg_write(retval, client,0xC802, 0x0028);		//cam_sensor_cfg_x_addr_start = 40
	i2c_reg_write(retval, client,0xC804, 0x020B);		//cam_sensor_cfg_y_addr_end = 523
	i2c_reg_write(retval, client,0xC806, 0x02AF);		//cam_sensor_cfg_x_addr_end = 687
	i2c_reg_write32(retval, client,0xC808, 0x019BFCC0);		//cam_sensor_cfg_pixclk = 27000000
	i2c_reg_write(retval, client,0xC80C, 0x0099);		//cam_sensor_cfg_fine_integ_time_min = 153
	i2c_reg_write(retval, client,0xC80E, 0x02F3	);	//cam_sensor_cfg_fine_integ_time_max = 755
	i2c_reg_write(retval, client,0xC810, 0x020B	);	//cam_sensor_cfg_frame_length_lines = 523
	i2c_reg_write(retval, client,0xC812, 0x035C	);	//cam_sensor_cfg_line_length_pck = 860
	i2c_reg_write(retval, client,0xC814, 0x0026	);	//cam_sensor_cfg_fine_correction = 38
	i2c_reg_write(retval, client,0xC816, 0x01E3	);	//cam_sensor_cfg_cpipe_last_row = 483
	i2c_reg_write(retval, client,0xC838, 0x0000	);	//cam_sensor_control_read_mode = 0
	i2c_reg_write(retval, client,0xC858, 0x0011	);	//cam_frame_scan_control = 17
	i2c_reg_write(retval, client,0xC968, 0x0280	);	//cam_output_width = 640
	i2c_reg_write(retval, client,0xC96A, 0x01E0	);	//cam_output_height = 480
	i2c_reg_write(retval, client,0xC864, 0x01	);	//cam_zoom_factor = 1
	i2c_reg_write(retval, client,0xC86C, 0x00	);	//cam_aet_aemode = 0
	i2c_reg_write(retval, client,0xC872, 0x0409	);	//cam_aet_ae_min_virt_int_time_pclk = 1033
	i2c_reg_write(retval, client,0xC882, 0x3C00	);	//cam_aet_max_frame_rate = 15360
	i2c_reg_write(retval, client,0xC884, 0x3C00	);	//cam_aet_min_frame_rate = 15360
	i2c_reg_write(retval, client,0xC924, 0x15	);	//cam_stat_calcmode = 21
}


int Load_CCM(struct i2c_client *client){
	int retval=0;
	i2c_reg_write(retval, client,VAR(18,0x0088), 0x01F2);
	i2c_reg_write(retval, client,VAR(18,0x008A), 0xFF6E);
	i2c_reg_write(retval, client,VAR(18,0x008C), 0xFFA0);
	i2c_reg_write(retval, client,VAR(18,0x008E), 0xFF76);
	i2c_reg_write(retval, client,VAR(18,0x0090), 0x0188);
	i2c_reg_write(retval, client,VAR(18,0x0092), 0x0002);
	i2c_reg_write(retval, client,VAR(18,0x0094), 0xFFC2);
	i2c_reg_write(retval, client,VAR(18,0x0096), 0xFF30);
	i2c_reg_write(retval, client,VAR(18,0x0098), 0x020E);
	i2c_reg_write(retval, client,VAR(18,0x009A), 0x01D9);
	i2c_reg_write(retval, client,VAR(18,0x009C), 0xFF00);
	i2c_reg_write(retval, client,VAR(18,0x009E), 0xFFF3);
	i2c_reg_write(retval, client,VAR(18,0x00A0), 0xFF94);
	i2c_reg_write(retval, client,VAR(18,0x00A2), 0x0132);
	i2c_reg_write(retval, client,VAR(18,0x00A4), 0xFFF3);
	i2c_reg_write(retval, client,VAR(18,0x00A6), 0x001A);
	i2c_reg_write(retval, client,VAR(18,0x00A8), 0xFE73);
	i2c_reg_write(retval, client,VAR(18,0x00AA), 0x02C2);
	i2c_reg_write(retval, client,VAR(18,0x00AC), 0x01AF);
	i2c_reg_write(retval, client,VAR(18,0x00AE), 0xFF93);
	i2c_reg_write(retval, client,VAR(18,0x00B0), 0xFFBE);
	i2c_reg_write(retval, client,VAR(18,0x00B2), 0xFF9E);
	i2c_reg_write(retval, client,VAR(18,0x00B4), 0x0176);
	i2c_reg_write(retval, client,VAR(18,0x00B6), 0xFFED);
	i2c_reg_write(retval, client,VAR(18,0x00B8), 0x0001);
	i2c_reg_write(retval, client,VAR(18,0x00BA), 0xFF78);
	i2c_reg_write(retval, client,VAR(18,0x00BC), 0x0187);
	pr_info("%s.%d retval(%x)\n",__func__,__LINE__,retval);
	return 0;
	
}

int Load_AWB(struct i2c_client *client){
	int retval=0;
	i2c_reg_write(retval, client,VAR( 18, 0x00BE), 0x006D);
	i2c_reg_write(retval, client,VAR( 18, 0x00C0), 0x0148);
	i2c_reg_write(retval, client,VAR( 18, 0x00C2), 0x009E);
	i2c_reg_write(retval, client,VAR( 18, 0x00C4), 0x011D);
	i2c_reg_write(retval, client,VAR( 18, 0x00C6), 0x00A2);
	i2c_reg_write(retval, client,VAR( 18, 0x00C8), 0x00B1);
	i2c_reg_write(retval, client,VAR( 18, 0x00CA), 0x0A8C);
	i2c_reg_write(retval, client,VAR( 18, 0x00CC), 0x0F0A);
	i2c_reg_write(retval, client,VAR( 18, 0x00CE), 0x1964);
	i2c_reg_write(retval, client,VAR( 18, 0x010C), 0x0000);
	i2c_reg_write(retval, client,VAR( 18, 0x010E), 0x0000);
	i2c_reg_write(retval, client,VAR( 18, 0x0110), 0x027F);
	i2c_reg_write(retval, client,VAR( 18, 0x0112), 0x01DF);
	i2c_reg_write(retval, client,VAR( 18, 0x00FA), 0x0040);
	i2c_reg_write(retval, client,VAR( 18, 0x00FC), 0x0035);
	i2c_reg_write8(retval, client,VAR( 18, 0x00E8), 0x03 );
	i2c_reg_write8(retval, client,VAR( 18, 0x00E9), 0x02  );
	i2c_reg_write(retval, client,VAR( 18, 0x00EA), 0x5D54 );
	i2c_reg_write(retval, client,VAR( 18, 0x00EC), 0xDCCE );
	i2c_reg_write(retval, client,VAR( 18, 0x00EE), 0x9A60 );
	i2c_reg_write(retval, client,VAR( 18, 0x00F0), 0x812A );
	i2c_reg_write(retval, client,VAR( 18, 0x00F2), 0x9C08 );
	i2c_reg_write(retval, client,VAR( 18, 0x00F4), 0x989D );
	i2c_reg_write(retval, client,VAR( 18, 0x00F6), 0x3D23  );
	i2c_reg_write(retval, client,VAR( 18, 0x00F8 ), 0x0624  );
	pr_info("%s.%d retval(%x)\n",__func__,__LINE__,retval);
	return 0;
}


// Color Pipe preference settings. Can be used as-is for any implementation,
// or can be altered per customer preferences. 
int Load_CPIPE_Preference(struct i2c_client *client){
int retval=0;	
 i2c_reg_write(retval, client,VAR( 18, 0x0128), 0x0018);
 i2c_reg_write(retval, client,VAR( 18, 0x012A), 0x0090);
 i2c_reg_write(retval, client,VAR( 18, 0x0148), 0x0093);
 i2c_reg_write(retval, client,VAR( 18, 0x014A), 0x0366);
 i2c_reg_write8(retval, client,VAR( 18, 0x0131), 0x07);
 i2c_reg_write8(retval, client,VAR( 18, 0x0134), 0x02);
 i2c_reg_write8(retval, client,VAR( 18, 0x0132), 0x02);
 i2c_reg_write8(retval, client,VAR( 18, 0x0135), 0x1F);
 i2c_reg_write(retval, client, VAR( 18, 0x0070), 0x0050);
 i2c_reg_write8(retval, client,VAR( 18, 0x0146), 0x28);
 i2c_reg_write8(retval, client,VAR( 18, 0x0147), 0x1E);	
 return 0;
}

/*
 * Function definitions
 */

int changeConfig(struct i2c_client *client){
	int retval;
		
	retval = sysmgrSetState(client,SYS_STATE_ENTER_CONFIG_CHANGE);
	return retval; 
}

int devwareSetCameraConfiguration(struct i2c_client *client/*interlaced, NTSC, custom, VGA60*/){
	int retval=0;
    //# always disable zoom
    //reg.CAM_ZOOM_FACTOR = 1

   
    // progresive
    i2c_reg_mask_set(retval, client,  VAR(0x12,0x0058),BIT(0), BIT(0));
	//reg.CAM_PORT_PARALLEL_CONTROL.CAM_PORT_PARALLEL_ENABLE = 1
	i2c_reg_mask_set(retval, client,VAR(0x12,0x0172), BIT(0), BIT(0));
    //   reg.CAM_PORT_PARALLEL_CONTROL.CAM_PORT_PARALLEL_SOURCE = 2  select progressive source	
	i2c_reg_mask_set(retval, client,VAR(0x12,0x0172), BIT(2)| BIT(1), BIT(2));
	// custop 
	//	reg.CAM_FRAME_SCAN_CONTROL.CAM_FRAME_SCAN_PROGRESSIVE_MODE = 2
	i2c_reg_mask_set(retval, client,VAR(0x12,0x0058), BIT(4)| BIT(3),BIT(3));

	//# Disable the composite port - due to a firmware defect (5664) this is not automatically
    //# disabled in the custom-progressive configuration. Note this variable is normally
    //# read-only, but we override it here

	//reg.CAM_PORT_COMPOSITE_CONTROL.rw = 1
	//reg.CAM_PORT_COMPOSITE_CONTROL.CAM_PORT_COMPOSITE_ENABLE.rw = 1
	//reg.CAM_PORT_COMPOSITE_CONTROL.CAM_PORT_COMPOSITE_ENABLE = 0
   


    retval =changeConfig(client);
	return retval;
} 

int set_camera_mode(struct i2c_client *client ,int mode){
	int retval=0;
	i2c_reg_write8(retval, client,VAR(0x12,0x0050), mode);	
	 return retval;
}

void camera_init(struct i2c_client *client ){
int ret ;
	
	ret = mt9v139_reset(client);
	ret = Load_PLL(client);	
	ret = Load_640X480(client);
	ret = changeConfig(client);
	ret = sysmgrGetState(client);
	
#if 0	
	set_camera_mode(client,2);
	ret =changeConfig(client);
	ret = sysmgrSetState(client,SYS_STATE_START_STREAMING);
	return 0;
	
	Load_CCM(client);
	Load_AWB(client);
	Load_CPIPE_Preference(client);
	ret = mt9v139_config(client);
	devwareSetCameraConfiguration(client);
	ret = sysmgrGetState(client);
	ret = sysmgrSetState(client,SYS_STATE_START_STREAMING);
	ret = sysmgrGetState(client);
#endif	
}


/*!
 * MT9V111 sensor configuration
 */
static int mt9v139_config(struct i2c_client *client)
{
int i;
int retval=0;	

	pr_info("In mt9v139_config\n");
	for(i=0;i<g_mode_info.init_data_size;i++){
		i2c_reg_mask_set(retval, client,g_mode_info.init_data_ptr[i].RegAddr,g_mode_info.init_data_ptr[i].Mask,g_mode_info.init_data_ptr[i].Val);
	}
	return 	retval;

}

/*!
 * mt9v139 sensor set saturtionn
 *
 * @param saturation   int

 * @return  Error code of 0.
 */
static int mt9v139_set_saturation(int saturation)
{
	u8 reg;
	u16 data;
	pr_debug("In mt9v139_set_saturation(%d)\n",
		saturation);


	return 0;
}

/*!
 * mt9v139 sensor set Auto Exposure measurement window mode configuration
 *
 * @param ae_mode      int
 * @return  Error code of 0 (no Error)
 */
static int mt9v139_set_ae_mode(int ae_mode)
{
	u8 reg;
	u16 data;

	pr_debug("In mt9v139_set_ae_mode(%d)\n",
		ae_mode);

	/* Currently this driver only supports auto and manual exposure
	 * modes. */
	if ((ae_mode > 1) || (ae_mode << 0))
		return -EPERM;

	return 0;
}




/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */

/*!
 * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num
 * s: pointer to standard V4L2 device structure
 * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure
 *
 * Gets slave interface parameters.
 * Calculates the required xclk value to support the requested
 * clock parameters in p.  This value is returned in the p
 * parameter.
 *
 * vidioc_int_g_ifparm returns platform-specific information about the
 * interface settings used by the sensor.
 *
 * Given the image capture format in pix, the nominal frame period in
 * timeperframe, calculate the required xclk frequency.
 *
 * Called on open.
 */
static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
{
	pr_debug("In mt9v139:ioctl_g_ifparm\n");

	if (s == NULL) {
		pr_err("   ERROR!! no slave device set!\n");
		return -1;
	}

	memset(p, 0, sizeof(*p));
	p->u.bt656.clock_curr = MT9V139_MCLK;
	p->if_type = V4L2_IF_TYPE_BT656;
	p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
//	p->u.bt656.mode =  V4L2_IF_TYPE_BT656_MODE_BT_8BIT;
	p->u.bt656.clock_min = MT9V139_CLK_MIN;
	p->u.bt656.clock_max = MT9V139_CLK_MAX;

	return 0;
}

/*!
 * Sets the camera power.
 *
 * s  pointer to the camera device
 * on if 1, power is to be turned on.  0 means power is to be turned off
 *
 * ioctl_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num
 * @s: pointer to standard V4L2 device structure
 * @on: power state to which device is to be set
 *
 * Sets devices power state to requrested state, if possible.
 * This is called on suspend and resume.
 */
static int ioctl_s_power(struct v4l2_int_device *s, int on)
{
	sensor_data_t *sensor = s->priv;
	int ret =0;
	pr_info("In mt9v139:ioctl_s_power %d\n",on);
	if(sensor_data.core_regulator==0){
		pr_info("%s.%d error regulator is null \n",__func__,__LINE__);
		return 0;
	}

	if (on && !sensor->power_on) {
		if(!regulator_is_enabled(sensor_data.core_regulator) ){
			ret = regulator_enable(sensor_data.core_regulator);
			if (ret  != 0) {
				pr_err("%s:core enable voltage error (%d)\n", __func__,ret);
			
			} else {
				pr_info("%s:core enable voltage ok\n", __func__);
			}	
		}
		
	//	ret = regulator_set_voltage(sensor_data.core_regulator,VOLTAGE_DIGITAL,VOLTAGE_DIGITAL);
		pr_info("%s:core set voltage %d\n", __func__,ret);
	}
	else if(!on && sensor->power_on){
		if(regulator_is_enabled(sensor_data.core_regulator)) {
			if (regulator_disable(sensor_data.core_regulator) != 0) {
				pr_err("%s:core disable voltage error\n", __func__);
			} else {
				pr_info("%s:core disable voltage ok\n", __func__);
			}
		}	
	}
	sensor->power_on = on;
	return 0;
}

/*!
 * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
 * @s: pointer to standard V4L2 device structure
 * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
 *
 * Returns the sensor's video CAPTURE parameters.
 */
static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
{
	int ret = 0;
	struct v4l2_captureparm *cparm = &a->parm.capture;
	/* s->priv points to sensor_data */

	pr_debug("In mt9v139:ioctl_g_parm\n");

	switch (a->type) {
	/* This is the only case currently handled. */
	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
		pr_debug("   type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
		memset(a, 0, sizeof(*a));
		a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		cparm->capability = sensor_data.streamcap.capability;
		cparm->timeperframe =
				sensor_data.streamcap.timeperframe;
		cparm->capturemode = sensor_data.streamcap.capturemode;
		ret = 0;
		break;

	/* These are all the possible cases. */
	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
	case V4L2_BUF_TYPE_VBI_CAPTURE:
	case V4L2_BUF_TYPE_VBI_OUTPUT:
	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
		pr_err("   type is not V4L2_BUF_TYPE_VIDEO_CAPTURE " \
			"but %d\n", a->type);
		ret = -EINVAL;
		break;

	default:
		pr_err("   type is unknown - %d\n", a->type);
		ret = -EINVAL;
		break;
	}

	return ret;
}

/*!
 * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
 * @s: pointer to standard V4L2 device structure
 * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
 *
 * Configures the sensor to use the input parameters, if possible.  If
 * not possible, reverts to the old parameters and returns the
 * appropriate error code.
 */
static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
{
	int ret = 0;
	struct v4l2_captureparm *cparm = &a->parm.capture;
	/* s->priv points to sensor_data */

	pr_debug("In mt9v139:ioctl_s_parm\n");

	switch (a->type) {
	/* This is the only case currently handled. */
	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
		pr_debug("   type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");

		/* Check that the new frame rate is allowed.
		 * Changing the frame rate is not allowed on this
		 *camera. */
		if (cparm->timeperframe.denominator !=
		    sensor_data.streamcap.timeperframe.denominator) {
			pr_err("ERROR: mt9v139: ioctl_s_parm: " \
			       "This camera does not allow frame rate "
			       "changes.\n");
			ret = -EINVAL;
		} else {
			sensor_data.streamcap.timeperframe =
						cparm->timeperframe;
		      /* Call any camera functions to match settings. */
		}

		/* Check that new capture mode is supported. */
		if ((cparm->capturemode != 0) &&
		    !(cparm->capturemode & V4L2_MODE_HIGHQUALITY)) {
			pr_err("ERROR: mt9v139: ioctl_s_parm: " \
				"unsupported capture mode\n");
			ret  = -EINVAL;
		} else {
			sensor_data.streamcap.capturemode =
						cparm->capturemode;
		      /* Call any camera functions to match settings. */
		      /* Right now this camera only supports 1 mode. */
		}
		break;

	/* These are all the possible cases. */
	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
	case V4L2_BUF_TYPE_VBI_CAPTURE:
	case V4L2_BUF_TYPE_VBI_OUTPUT:
	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
		pr_err("   type is not V4L2_BUF_TYPE_VIDEO_CAPTURE " \
			"but %d\n", a->type);
		ret = -EINVAL;
		break;

	default:
		pr_err("   type is unknown - %d\n", a->type);
		ret = -EINVAL;
		break;
	}

	return 0;
}

/*!
 * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
 * @s: pointer to standard V4L2 device structure
 * @f: pointer to standard V4L2 v4l2_format structure
 *
 * Returns the sensor's current pixel format in the v4l2_format
 * parameter.
 */
static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
{
	sensor_data_t *sensor = s->priv;
	/* s->priv points to sensor_data */

	pr_debug("In mt9v139:ioctl_g_fmt_cap.\n");
	pr_debug("   Returning size of %dx%d\n",
	sensor->pix.width, sensor->pix.height);

	f->fmt.pix = sensor->pix;

	return 0;
}

/*!
 * ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl
 * @s: pointer to standard V4L2 device structure
 * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure
 *
 * If the requested control is supported, returns the control information
 * from the video_control[] array.  Otherwise, returns -EINVAL if the
 * control is not supported.
 */
static int ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qc)
{
	pr_debug("In mt9v139:ioctl_queryctrl\n");

	return 0;
}



/*!
 * ioctl_g_chip_ident - V4L2 sensor interface handler for
 *			VIDIOC_DBG_G_CHIP_IDENT ioctl
 * @s: pointer to standard V4L2 device structure
 * @id: pointer to int
 *
 * Return 0.
 */
static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
{
	((struct v4l2_dbg_chip_ident *)id)->match.type =
					V4L2_CHIP_MATCH_I2C_DRIVER;
	strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "mt9v139_camera");

	return 0;
}



/*!
 * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
 * @s: pointer to standard V4L2 device structure
 * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
 *
 * If the requested control is supported, returns the control's current
 * value from the video_control[] array.  Otherwise, returns -EINVAL
 * if the control is not supported.
 */
static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
{
	pr_debug("In mt9v139:ioctl_g_ctrl\n");

	switch (vc->id) {
	case V4L2_CID_BRIGHTNESS:
		pr_debug("   V4L2_CID_BRIGHTNESS\n");
		vc->value = sensor_data.brightness;
		break;
	case V4L2_CID_CONTRAST:
		pr_debug("   V4L2_CID_CONTRAST\n");
		vc->value = sensor_data.contrast;
		break;
	case V4L2_CID_SATURATION:
		pr_debug("   V4L2_CID_SATURATION\n");
		vc->value = sensor_data.saturation;
		break;
	case V4L2_CID_HUE:
		pr_debug("   V4L2_CID_HUE\n");
		vc->value = sensor_data.hue;
		break;
	case V4L2_CID_AUTO_WHITE_BALANCE:
		pr_debug(
			"   V4L2_CID_AUTO_WHITE_BALANCE\n");
		vc->value = 0;
		break;
	case V4L2_CID_DO_WHITE_BALANCE:
		pr_debug(
			"   V4L2_CID_DO_WHITE_BALANCE\n");
		vc->value = 0;
		break;
	case V4L2_CID_RED_BALANCE:
		pr_debug("   V4L2_CID_RED_BALANCE\n");
		vc->value = sensor_data.red;
		break;
	case V4L2_CID_BLUE_BALANCE:
		pr_debug("   V4L2_CID_BLUE_BALANCE\n");
		vc->value = sensor_data.blue;
		break;
	case V4L2_CID_GAMMA:
		pr_debug("   V4L2_CID_GAMMA\n");
		vc->value = 0;
		break;
	case V4L2_CID_EXPOSURE:
		pr_debug("   V4L2_CID_EXPOSURE\n");
		vc->value = sensor_data.ae_mode;
		break;
	case V4L2_CID_AUTOGAIN:
		pr_debug("   V4L2_CID_AUTOGAIN\n");
		vc->value = 0;
		break;
	case V4L2_CID_GAIN:
		pr_debug("   V4L2_CID_GAIN\n");
		vc->value = 0;
		break;
	case V4L2_CID_HFLIP:
		pr_debug("   V4L2_CID_HFLIP\n");
		vc->value = 0;
		break;
	case V4L2_CID_VFLIP:
		pr_debug("   V4L2_CID_VFLIP\n");
		vc->value = 0;
		break;
	default:
		pr_debug("   Default case\n");
		return -EPERM;
		break;
	}

	return 0;
}

/*!
 * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
 * @s: pointer to standard V4L2 device structure
 * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
 *
 * If the requested control is supported, sets the control's current
 * value in HW (and updates the video_control[] array).  Otherwise,
 * returns -EINVAL if the control is not supported.
 */
static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
{
	int retval = 0;

	pr_debug("In mt9v139:ioctl_s_ctrl %d\n",
		vc->id);

	switch (vc->id) {
	case V4L2_CID_BRIGHTNESS:
		pr_debug("   V4L2_CID_BRIGHTNESS\n");
		break;
	case V4L2_CID_CONTRAST:
		pr_debug("   V4L2_CID_CONTRAST\n");
		break;
	case V4L2_CID_SATURATION:
		pr_debug("   V4L2_CID_SATURATION\n");
		//retval = mt9v139_set_saturation(vc->value);
		break;
	case V4L2_CID_HUE:
		pr_debug("   V4L2_CID_HUE\n");
		break;
	case V4L2_CID_AUTO_WHITE_BALANCE:
		pr_debug(
			"   V4L2_CID_AUTO_WHITE_BALANCE\n");
		break;
	case V4L2_CID_DO_WHITE_BALANCE:
		pr_debug(
			"   V4L2_CID_DO_WHITE_BALANCE\n");
		break;
	case V4L2_CID_RED_BALANCE:
		pr_debug("   V4L2_CID_RED_BALANCE\n");
		break;
	case V4L2_CID_BLUE_BALANCE:
		pr_debug("   V4L2_CID_BLUE_BALANCE\n");
		break;
	case V4L2_CID_GAMMA:
		pr_debug("   V4L2_CID_GAMMA\n");
		break;
	case V4L2_CID_EXPOSURE:
		pr_debug("   V4L2_CID_EXPOSURE\n");
		//retval = mt9v139_set_ae_mode(vc->value);
		break;
	case V4L2_CID_AUTOGAIN:
		pr_debug("   V4L2_CID_AUTOGAIN\n");
		break;
	case V4L2_CID_GAIN:
		pr_debug("   V4L2_CID_GAIN\n");
		break;
	case V4L2_CID_HFLIP:
		pr_debug("   V4L2_CID_HFLIP\n");
		break;
	case V4L2_CID_VFLIP:
		pr_debug("   V4L2_CID_VFLIP\n");
		break;
	default:
		pr_debug("   Default case\n");
		retval = -EPERM;
		break;
	}

	return retval;
}

/*!
 * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
 * @s: pointer to standard V4L2 device structure
 */
static int ioctl_init(struct v4l2_int_device *s)
{
	sensor_data_t  *camera = s->priv;
	pr_info("In mt9v139:ioctl_init\n");
	camera_init(camera->i2c_client);
	return 0;
}

/*!
 * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
 * @s: pointer to standard V4L2 device structure
 *
 * Initialise the device when slave attaches to the master.
 */
static int ioctl_dev_init(struct v4l2_int_device *s)
{
	sensor_data_t  *camera = s->priv;
	uint32_t clock_rate = MT9V139_MCLK;
	pr_info("In mt9v139:ioctl_dev_init\n");
	set_mclk_rate(&camera->mclk, camera->csi);

	return 0;
}


/*!
 * ioctl_enum_framesizes - V4L2 sensor interface handler for
 *			   VIDIOC_ENUM_FRAMESIZES ioctl
 * @s: pointer to standard V4L2 device structure
 * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
 *
 * Return 0 if successful, otherwise -EINVAL.
 */
static int ioctl_enum_framesizes(struct v4l2_int_device *s,
				 struct v4l2_frmsizeenum *fsize)
{
	sensor_data_t *sensor = s->priv;

	//if (fsize->index > ov5642_mode_MAX)
	//	return -EINVAL;

	fsize->pixel_format =  sensor->pix.pixelformat;
	fsize->discrete.width = 640;
	fsize->discrete.height = 480;
	
	return 0;
}


/*!
 * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
 * @s: pointer to standard V4L2 device structure
 * @fmt: pointer to standard V4L2 fmt description structure
 *
 * Return 0.
 */
static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
			      struct v4l2_fmtdesc *fmt)
{
	sensor_data_t *sensor = s->priv;

	fmt->pixelformat = sensor->pix.pixelformat;
	return 0;
}



/*!
 * This structure defines all the ioctls for this module and links them to the
 * enumeration.
 */
static struct v4l2_int_ioctl_desc mt9v139_ioctl_desc[] = {

	{vidioc_int_dev_init_num, (v4l2_int_ioctl_func*)ioctl_dev_init},

	/*!
	 * Delinitialise the dev. at slave detach.
	 * The complement of ioctl_dev_init.
	 */
/*	{vidioc_int_dev_exit_num, (v4l2_int_ioctl_func *) ioctl_dev_exit}, */

	{vidioc_int_s_power_num, (v4l2_int_ioctl_func*) ioctl_s_power},
	{vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*) ioctl_g_ifparm},
/*	{vidioc_int_g_needs_reset_num,
				(v4l2_int_ioctl_func *) ioctl_g_needs_reset}, */
/*	{vidioc_int_reset_num, (v4l2_int_ioctl_func *) ioctl_reset}, */
	{vidioc_int_init_num, (v4l2_int_ioctl_func*) ioctl_init},

	/*!
	 * VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type.
	 */
	{vidioc_int_enum_fmt_cap_num,
		(v4l2_int_ioctl_func *) ioctl_enum_fmt_cap}, 

	/*!
	 * VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type.
	 * This ioctl is used to negotiate the image capture size and
	 * pixel format without actually making it take effect.
	 */
/*	{vidioc_int_try_fmt_cap_num,
				(v4l2_int_ioctl_func *) ioctl_try_fmt_cap}, */

	{vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func*) ioctl_g_fmt_cap},

	/*!
	 * If the requested format is supported, configures the HW to use that
	 * format, returns error code if format not supported or HW can't be
	 * correctly configured.
	 */
/*	{vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */

	{vidioc_int_g_parm_num, (v4l2_int_ioctl_func*) ioctl_g_parm},
	{vidioc_int_s_parm_num, (v4l2_int_ioctl_func*) ioctl_s_parm},
/*	{vidioc_int_queryctrl_num, (v4l2_int_ioctl_func *) ioctl_queryctrl}, */
	{vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func*) ioctl_g_ctrl},
	{vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func*) ioctl_s_ctrl},
	{vidioc_int_g_chip_ident_num,
				(v4l2_int_ioctl_func *)ioctl_g_chip_ident},
	{vidioc_int_enum_framesizes_num,
					(v4l2_int_ioctl_func *)ioctl_enum_framesizes},
				
};

static struct v4l2_int_slave mt9v139_slave = {
	.ioctls = mt9v139_ioctl_desc,
	.num_ioctls = ARRAY_SIZE(mt9v139_ioctl_desc),
};

static struct v4l2_int_device mt9v139_int_device = {
	.module = THIS_MODULE,
	.name = "mt9v139",
	.type = v4l2_int_type_slave,
	.u = {
		.slave = &mt9v139_slave,
		},
};

/*!
 * mt9v139 I2C probe function
 * Function set in i2c_driver struct.
 * Called by insmod mt9v139_camera.ko.
 *
 * @return  Error code indicating success or failure
 */
static int mt9v139_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	int retval=0;
	u16 chipid=0;
	struct mxc_camera_platform_data *plat_data = client->dev.platform_data;

	pr_info("In mt9v139_probe if(%s) i2cname(%s)\n", id->name,client->name);


	i2c_reg_read(chipid, client, 0x0000);
	pr_info("%s chip_id(%x) \n\r",__func__,chipid);		
	
		switch (chipid) {
		case 0x2285:
			pr_info("%s mt9v129 \n\r",__func__,chipid);	
			break;
		default:
			dev_err(&client->dev, "Product ID error %04x\n", chipid);
		//	return -ENODEV;
		}


	/* Set initial values for the sensor struct. */
	memset(&sensor_data, 0, sizeof(sensor_data));
	sensor_data.i2c_client = client;
	sensor_data.pix.pixelformat = V4L2_PIX_FMT_UYVY;
	sensor_data.pix.width = 640;
	sensor_data.pix.height = 480;
	sensor_data.streamcap.capability = 0; /* No higher resolution or frame
						* frame rate changes supported.
						*/
	sensor_data.streamcap.timeperframe.denominator = 30;
	sensor_data.streamcap.timeperframe.numerator = 1;

	mt9v139_int_device.priv = &sensor_data;


	sensor_data.mclk  = plat_data->mclk;
	sensor_data.csi   = plat_data->csi;
	sensor_data.platform_data = plat_data;


	pr_info("   type is %d (expect %d)\n",
		mt9v139_int_device.type, v4l2_int_type_slave);
	pr_info("   num ioctls is %d\n",
		mt9v139_int_device.u.slave->num_ioctls);

	
	if (plat_data->core_regulator) {
		sensor_data.core_regulator = regulator_get(&client->dev,
					       plat_data->core_regulator);
		if (IS_ERR(sensor_data.core_regulator)) {
			sensor_data.core_regulator = NULL;	
			pr_info("%s.%d error get regulator\n",__func__,__LINE__);
		}	
	}
	

	/* This function attaches this structure to the /dev/video0 device.
	 * The pointer in priv points to the sensor_data structure here.*/
	retval = v4l2_int_device_register(&mt9v139_int_device);

	pr_info("%s exit code(%d)\n",__func__,retval);

	

	return retval;

ExitError:
	return -1;
}

/*!
 * Function set in i2c_driver struct.
 * Called on rmmod mt9v139_camera.ko
 */
static int mt9v139_remove(struct i2c_client *client)
{

	pr_info("%s \n",__func__);
	if(sensor_data.power_on	){
		if(sensor_data.core_regulator)
			regulator_disable(sensor_data.core_regulator);
	}
	
	v4l2_int_device_unregister(&mt9v139_int_device);
	return 0;
}

/*!
 * MT9V111 init function.
 * Called by insmod mt9v139_camera.ko.
 *
 * @return  Error code indicating success or failure
 */
static __init int mt9v139_init(void)
{
	u8 err;

	pr_info("In mt9v139_init\n");

	/* Allocate memory for state structures. */

	/* Tells the i2c driver what functions to call for this driver. */
	err = i2c_add_driver(&mt9v139_i2c_driver);
	if (err != 0)
		pr_err("%s:driver registration failed, error=%d \n",
		       __func__, err);

	return err;
}

/*!
 * MT9V111 cleanup function.
 * Called on rmmod mt9v139_camera.ko
 *
 * @return  Error code indicating success or failure
 */
static void __exit mt9v139_clean(void)
{
	pr_info("In mt9v139_clean()\n");
	
	i2c_del_driver(&mt9v139_i2c_driver);
}

module_init(mt9v139_init);
module_exit(mt9v139_clean);

MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("Mt9v111 Camera Driver");
MODULE_LICENSE("GPL");
